﻿//-----------------------------------------------------------------------
// <copyright company="www.3WayWebdesign.de">
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
//
// <author>Michael Morbach</author>
// <email>Michael@3waywebdesign.de</email>
// <web>http://www.3waywebdesign.de</web>
//-----------------------------------------------------------------------

namespace Tww.IBAN.IBANUtilities.Parser
{
    #region Imports

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Tww.IBAN.IBANUtilities.Constants;
    using Tww.IBAN.IBANUtilities.Model;


    #endregion

    public class DefaultIBANParser : IIBANParser
    {

        /// <summary>
        /// Parses a string and returns a new IBANModel with the containing informations
        /// </summary>
        /// <param name="ibanInput">Inputstring</param>
        /// <returns>IBANModel Container</returns>
        public Model.IBANModel Parse( string ibanInput )
        {
            // First 2 Chars represent the country
            var cleanedIBAN = CharTransformationChart.NormalizeIBAN( ibanInput );
            var country = String.Concat( cleanedIBAN.Take( 2 ) ).ToLower();
            var countryStructure = CountryCodes.CountryIBANStructes.SingleOrDefault( c => c.CountryShortCode == country );

            if ( countryStructure == null )
            {
                throw new ArgumentException( string.Format( "IBAN does not begin with a valid countrycode. Please provide correct information. - {0}", cleanedIBAN ) );
            }

            if ( cleanedIBAN.Length > countryStructure.IBANMaxLength )
            {
                throw new ArgumentException( string.Format( "IBAN does exceed the maximum allowed length for this country. Please provide correct information. - {0}", cleanedIBAN ) );
            }

            string countrycode = string.Empty;
            string bankcode = string.Empty;
            string branch = string.Empty;
            string account = string.Empty;
            string misc = string.Empty;

            var positionIndex = 0;
            var countryStructureCode = CharTransformationChart.NormalizeIBAN( countryStructure.IBANStructure );

            foreach ( var character in cleanedIBAN )
            {
                var structureCodeIndex = countryStructureCode[ positionIndex ];

                switch ( structureCodeIndex )
                {
                    // Country
                    case 'c':
                        countrycode += character;
                        break;

                    // checksum
                    case 'p':
                        // - No action yet
                        break;

                    // bankcode
                    case 'b':
                        bankcode += character;
                        break;

                    // branch
                    case 'r':
                        branch += character;
                        break;

                    // account
                    case 'a':
                        account += character;
                        break;

                    // misc
                    case 'i':
                        misc += character;
                        break;
                }

                positionIndex++;
            }

            return new IBANModel( country, account, bankcode, branch, misc );
        }
    }
}
